<?php

namespace App\Http\Controllers\QH_Api;

use App\Http\Controllers\TK_Api\ApiBaseController;
use App\Models\Document;
use App\Models\DocumentCategory;
use App\Models\DocumentOrder;
use App\Models\DocumentTag;
use App\Models\TQ_Config;
use App\Models\User;
use App\Service\Wechat\WechatPayService;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
use Throwable;

class DocumentController extends ApiBaseController
{

    public function common() {
        // 返回两个卡片
        $homeConfig = TQ_Config::where('key', 'document_config')->first();
        if ($homeConfig) {
            $cards = json_decode($homeConfig->value, true);
            if ($cards) {
                $cards = [
                    [
                        'image' => $cards['card1_image'],
                        'jump_type' => $cards['card1_jump_type'],
                        'jump_target' => $cards['card1_jump_target'],
                        'jump_params' => $cards['card1_jump_params'],
                    ],
                    [
                        'image' => $cards['card2_image'],
                        'jump_type' => $cards['card2_jump_type'],
                        'jump_target' => $cards['card2_jump_target'],
                        'jump_params' => $cards['card2_jump_params'],
                    ]
                ];
            }else {
                $cards = [];
            }
        }else {
            $cards = [];
        }

        // 当前省份下的分类
        if (!empty(request('province'))) {
            $categories = DocumentCategory::select(['id', 'name'])->where('province', 'like', '%'.request('province').'%')->get();
        }else {
            $categories = DocumentCategory::select(['id', 'name'])->get();
        }

        $categoryIds = $categories->pluck('id')->toArray();

        $documentIds = Document::whereHas('category', function ($query) use ($categoryIds) {
            $query->whereIn('categoryId', $categoryIds);
        })->orderByRaw('sort asc, id asc')->pluck('id')->toArray();


        $tagIds = DB::table('qh_document_tag_relation')->whereIn('documentId', $documentIds)->pluck('tagId')->toArray();

        // 当前分类下文档的标签
        $tags = DocumentTag::whereIn('id', array_unique($tagIds))->select(['id', 'name'])->get();

        return $this->restful([
            'categories' => $categories,
            'tags' => $tags,
            'cards' => $cards
        ]);
    }

    /**
     * 获取列表
     * @return JsonResponse|object
     */
    public function list() {
        $reqData = request()->all();
        $reqData['disabled'] = 0;
        $list = Document::filter($reqData)
            ->select([
                'id',
                'title',
                'downloadCount',
                'viewCount',
                'thumb',
                'print',
                'fileFormat',
                'fileSize',
                'amount'
            ])
            ->orderByRaw('sort asc, id asc')
            ->paginateFilter(\request('perPage', 10));

        return $this->restful($list);
    }

    /**
     * 文档详情
     * @param $id
     * @return JsonResponse|object
     */
    public function show($id) {
        $document = Document::findOrFail($id);

        return $this->restful($document);
    }

    /**
     * 下单
     * @throws Exception
     * @throws GuzzleException
     * @throws Throwable
     */
    public function buy(WechatPayService $payService) {
        $id = request('id');
        $address = request('address');
        // if (!$address) {
        //     return $this->restful(null, false, '请输入地址');
        // }
        $document = Document::findOrFail($id);

        $tradeNo = 'NO'.time().rand(1000, 9999);
        $price = $document->amount * 100;    // 价格，数据库记录的是元，需要x100

        DB::beginTransaction();

        // 微信下单
        $result = $payService->documentOrder([
            'body' => '购买资料',
            'tradeNo' => $tradeNo,
            'fee' => $price,
            'openid' => $this->user->wxOpenid
        ]);

        try {
            $order = new DocumentOrder([
                'userId' => $this->user->id,
                'documentId' => $document->id,
                'tradeNo' => $tradeNo,
                'price' => $document->amount,
                'buyAt' => Carbon::now(),
                'address' => $address,
                'wxNonceStr' => $result['nonce_str'],
                'wxSign' => $result['sign'],
                'wxPrepayId' => $result['prepay_id']
            ]);

            $order->save();

            $payInfo = $payService->sign($result['prepay_id']);
            unset($payInfo['appId']);
            $payInfo['documentId'] = $document->id;
            $payInfo['orderId'] = $order->id;
            $payInfo['tradeNo'] = $order->tradeNo;
            $payInfo['price'] = $price;

            DB::commit();

            return $this->restful($payInfo);
        }catch (Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), (array)$e);
            throw new Exception('下单失败', 200);
        }
    }

    /**
     * 微信支付成功通知
     * @param WechatPayService $payService
     * @return Response
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    public function wechatNotify(WechatPayService $payService) {
        Log::debug('[微信支付通知开始]'. Carbon::now()->format('Y-m-d H:i:s'));
        $response = $payService->app->handlePaidNotify(function ($message, $fail) {
            try {
                $order = DocumentOrder::where('tradeNo', $message['out_trade_no'])->first();
                if ($order) {
                    if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                        // 用户是否支付成功
                        if (array_get($message, 'result_code') === 'SUCCESS') {
                            if ($order->status == 1) {
                                Db::transaction(function () use ($order, $message) {
                                    $order->status = 2;
                                    $order->wxTradeNo = $message['transaction_id']; // 微信订单号
                                    $order->payAt = Carbon::now();
                                    $order->save();

                                    $user = User::find($order->userId);
                                    if (!$user) throw new Exception();
                                    // 将文档添加到用户
                                    $result = DB::table('qh_user_has_document')->insert([
                                        'userId' => $user->id,
                                        'documentId' => $order->documentId,
                                        'orderId' => $order->id,
                                        'type' => 1,
                                        'created_at' => Carbon::now()
                                    ]);
                                    if (!$result) throw new Exception();
                                });
                            }
                        }
                    } else {
                        return $fail('通信失败，请稍后再通知我');
                    }
                }
                Log::info('微信支付通知处理成功，订单ID：'.$order->id);
                return true;
            }catch (Exception $e) {
                Log::error('微信支付通知处理异常');
                Log::error(json_encode($e->getMessage()));
                Log::error(json_encode($e->getLine()));
                Log::error(json_encode($e->getFile()));
            }

            return $fail('通信失败，请稍后再通知我');
        });

        return $response->send();
    }

    /**
     * 微信退款成功通知
     * @param WechatPayService $payService
     * @return Response
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    public function wechatRefundNotify(WechatPayService $payService) {
        $response = $payService->app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
            Log::debug('[微信退款通知]', [$message, $reqInfo]);

            if ($reqInfo['refund_status'] === 'SUCCESS') {
                $order = DocumentOrder::where('refundTradeNo', $reqInfo['out_refund_no'])->first();
                if (!$order) {
                    Log::error('[微信退款通知] 订单没找到，退款单号：'.$reqInfo['out_refund_no']);
                    return $fail('内部错误，请稍后再试');
                }
                if ($order->status == 9) return true;

                $order->status = 9;

                // 文档
                $buyRelation = DB::table('qh_user_has_document')->where('userId', $order->userId)->where('orderId', $order->id)->first();
                if ($buyRelation) {
                    if ($buyRelation->type == 1) {
                        DB::table('qh_user_has_document')->where('userId', $order->userId)->where('orderId', $order->id)->delete();
                    }
                    // elseif ($buyRelation->type == 2) {
                    //
                    // }
                }
                $order->save();
                return true;
            }else {
                Log::debug('[退款通知]退款失败，退款单号：'.$reqInfo['out_refund_no']);
                return $fail('内部错误，请稍后再试');
            }
        });

        return $response->send();
    }

    /**
     * 我购买的文档
     * @return JsonResponse|object
     */
    public function getMyBuyDocuments() {
        $documents = $this->user->document()->select([
            'title',
            'downloadCount',
            'viewCount',
            'thumb',
            'fileFormat',
            'fileSize',
            'print',
            'amount'
        ])->paginate(10);

        return $this->restful($documents);
    }

    /**
     * 我收藏的文档
     * @return JsonResponse|object
     */
    public function getMyCollectDocuments() {
        $documentIds = DB::table('qh_user_collect_document')->where('userId', $this->user->id)->orderByDesc('id')->pluck('documentId')->toArray();

        $documents = Document::whereIn('id', $documentIds)->select([
            'id',
            'title',
            'downloadCount',
            'viewCount',
            'thumb',
            'fileFormat',
            'fileSize',
            'print',
            'amount'
        ])->paginate(10);

        return $this->restful($documents);
    }

    /**
     * 收藏取消收藏
     * @param $id
     * @return JsonResponse|object
     */
    public function collectSwitch($id) {
        $r = DB::table('qh_user_collect_document')
            ->where('userId', $this->user->id)
            ->where('documentId', $id)
            ->first();
        if (!$r) {
            DB::table('qh_user_collect_document')->insert([
                'userId' => $this->user->id,
                'documentId' => $id,
                'created_at' => Carbon::now()
            ]);
        }else {
            DB::table('qh_user_collect_document')
                ->where('userId', $this->user->id)
                ->where('documentId', $id)
                ->delete();
        }
        return $this->restful();
    }

    /**
     * 获取下载链接
     * @param $id
     * @return JsonResponse|object
     */
    public function downloadDocument($id) {
        $document = Document::findOrFail($id);

        $downloadUrl = [];
        // $file1 = str_replace(config('filesystems.disks.aliyun.domain'), '', $document->file1);
        // $downloadUrl[] = \Storage::disk('aliyun')->temporaryUrl($file1, Carbon::now()->addHours(12));
        $downloadUrl[] = $document->file1;
        if ($document->file2) {
            // $file2 = str_replace(config('filesystems.disks.aliyun.domain'), '', $document->file2);
            // $downloadUrl[] = \Storage::disk('aliyun')->temporaryUrl($file2, Carbon::now()->addHours(12));
            $downloadUrl[] = $document->file2;
        }

        $data = [
            'id' => $document->id,
            'title' => $document->title,
            'fileFormat' => $document->fileFormat,
            'fileSize' => $document->fileSize,
            'downloadUrl' => $downloadUrl
        ];

        return $this->restful($data);
    }

    /**
     * 统计文档数据
     * type==1阅读次数，type==2下载次数
     * @return JsonResponse|object
     */
    public function documentStatic() {
        $id = request('id');
        $type = request('type');
        if (empty($id) || empty($type) || ($type != 1 && $type != 2)) {
            return $this->restful();
        }
        $document = Document::find($id);
        if (!$document) return $this->restful();

        // 冷却机制，3600秒，1小时
        $cacheKey = 'DocumentCooldown:user='.$this->user->id.'|document_static='.$id.'|type='.$type;
        $cacheValue = \Cache::get($cacheKey);
        if ($cacheValue && now()->diffInSeconds($cacheValue) < 3600) {
            return $this->restful();
        }
        \Cache::put($cacheKey, now(), 3600);

        if ($type == 1) $document->viewCount += 1;
        if ($type == 2) $document->downloadCount += 1;
        $document->save();
        return $this->restful();
    }

    /**
     * 获取我的文档订单
     * @return JsonResponse|object
     */
    public function getMyDocumentOrders() {
        $requestParams = request()->all();
        $requestParams['userId'] = $this->user->id;

        DocumentOrder::where('userId', $this->user->id)
            ->where('status', 1)
            ->whereNull('payAt')
            ->whereRaw('buyAt > NOW() - INTERVAL 30 MINUTE')
            ->delete();

        $list = DocumentOrder::filter($requestParams)
            ->with(['document' => function($q) {
                $q->select([
                    'id',
                    'categoryId',
                    'title'
                ]);
            }])
            ->orderByDesc('id')
            ->paginateFilter(request('perPage', 5));

        return $this->restful($list);
    }
}
